package com.it.water.controller.VideoController;

import com.it.water.common.Result;
import com.it.water.rtsp.MediaVideoTransfer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URL;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author IT_CREAT <br/> HelloWord505 <br/> <a href=mailto:2038322151@qq.com>Miraitowa_zcx<a/>
 * @version 1.1.0
 * @since 22024-04-14
 */
@Slf4j
@Controller
@CrossOrigin(origins = "*")
public class IndexController {
    AtomicInteger sign = new AtomicInteger();
    ConcurrentHashMap<Integer, String> pathMap = new ConcurrentHashMap<>();
    ConcurrentHashMap<Integer, PipedOutputStream> outputStreamMap = new ConcurrentHashMap<>();
    ConcurrentHashMap<Integer, PipedInputStream> inputStreamMap = new ConcurrentHashMap<>();

    @PostMapping("/putVideo")
    @ResponseBody
    public Result<Integer> putVideoPath(@RequestBody Map<String, String> path) {
        log.info("进来了: {}", path);

        String urlStr = path.get("path");
        if (urlStr == null || urlStr.isEmpty()) {
            return Result.error("路径不能为空");
        }

        try {
            String newUrlStr = urlStr.replace("rtsp://", "");
            URL url = new URL("https://" + newUrlStr);

            String host = url.getHost();
            int port = url.getPort() != -1 ? url.getPort() : 554;

            // 尝试建立 TCP 连接至 RTSP 服务器，超时时间为 5 秒
            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(host, port), 5000);

            // 连接成功，关闭 Socket 并继续执行原有逻辑
            socket.close();
            int id = sign.getAndIncrement();
            pathMap.put(id, urlStr);
            PipedOutputStream pipedOutputStream = new PipedOutputStream();
            PipedInputStream pipedInputStream = new PipedInputStream();
            pipedOutputStream.connect(pipedInputStream);
            outputStreamMap.put(id, pipedOutputStream);
            inputStreamMap.put(id, pipedInputStream);
            return Result.success(id);
        } catch (IOException e) {
            log.error("测试 RTSP 连通性时发生异常: {}", e.getMessage(), e);
            return Result.error("连接失败");
        }
    }

    @GetMapping("/getVideo")
    public void getVideo(HttpServletResponse response, int id) {
        log.info("进来了{}", id);
//        String path = pathMap.get(id);
        String fileName = UUID.randomUUID().toString();
        response.addHeader("Content-Disposition", "attachment;filename=" + fileName + ".flv");
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            write(id, outputStream);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            inputStreamMap.remove(id);
            outputStreamMap.remove(id);
        }
    }

    private void write(int id, OutputStream outputStream) {
        try {
            String path = pathMap.get(id);
            PipedOutputStream pipedOutputStream = outputStreamMap.get(id);
            new Thread(() -> {
                MediaVideoTransfer mediaVideoTransfer = new MediaVideoTransfer();
                mediaVideoTransfer.setOutputStream(pipedOutputStream);
                mediaVideoTransfer.setRtspTransportType("tcp");
                mediaVideoTransfer.setRtspUrl(path);
                mediaVideoTransfer.live();
            }).start();

            print(inputStreamMap.get(id), outputStream);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            close(inputStreamMap.get(id), outputStreamMap.get(id), outputStream);
        }
    }

    private void print(InputStream inputStream, OutputStream outputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int length;
        while ((length = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, length);
        }
    }

    private void close(Closeable... closeables) {
        for (Closeable closeable : closeables) {
            if (closeable != null) {
                try {
                    closeable.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }
}
